<?php

namespace app\console;

use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\facade\Cache;
use think\facade\Env;

class GetGoods extends Command
{
    public $max_precess = 4;
    public $mpid = 0;
    public $works = [];
    public $new_index = 0;
    public $fields = [  //这些字段每个页面有很多个,需要循环采集  这个属性中包含两个字段   title和url
                        'title' => [
                            'select' => '//*[@id="list"]/dl/dd/a',
                            'node'   => 'nodeValue',
                        ],
    ];

    protected function configure()
    {
        // 指令配置
        $this->setName('getgoods')
            ->addOption('debug', null, Option::VALUE_REQUIRED, 'debug option')
            ->setDescription('get goods info');
        // 设置参数

    }

    protected function execute(Input $input, Output $output) {
        //先采集列表页，存入缓存
        //$url = Cache::get('goods_list_url');
        //$redis = new \Redis();
        //$redis->connect('127.0.0.1', 6379);
        $output->writeln('列表页采集任务开始');
        //$redis->close();
        swoole_set_process_name('php-think:con');
        $this->mpid = posix_getpid();
        $this->Prun();
        $this->processWait();

        $output->writeln('get start');
    }

    public function Prun() {
        for ($i = 0; $i < $this->max_precess; $i++) {
            $this->CreateProcess();
        }
    }

    public function CreateProcess($index = null) {
        $process = new \swoole_process(function (\swoole_process $worker) use ($index) {
            if (is_null($index)) {
                $index = $this->new_index;
                $this->new_index++;
            }
            $redis = new \Redis();
            $redis->connect('127.0.0.1', '6379', 2);
            swoole_set_process_name(sprintf('php-think:son-%s', $this->new_index));
            for ($j = 0; $j < 10000; $j++) {
                $this->checkMpid($worker); //当前进程pid
                try {
                    $redis->ping();
                } catch (\RedisException $e) {
                    echo $e->getMessage();
                    exit;
                }
                if ($redis->lLen('goods_list') != 0) {
                    $goods = $redis->rPop('goods_list');
                } else {
                    dump("endTime: " . date("H:i:s") . 'maybe error or finished');
                    exit;
                }
                if (empty($goods)) {
                    exit;
                }
                $goods = json_decode($goods, true);
                foreach($goods as $k=>$v){
                    $html = curl_get($v);
                    $list = getContent($html, '//div[@id="imgList"]/ul/ul/li');
                    $bug = Env::get('app_path') . 'console/debug/list.php';
                    if (empty($list)) {    //没爬到数据
                        file_put_contents($bug, '"'.$v . '",', FILE_APPEND);
                        echo 'get goods list error - ' . PHP_EOL;
                        continue;
                    }
                    echo $k .PHP_EOL;
                    Cache::set('goods_list_' . $k, $list);
                }

            }
            //exit('进程任务数量不足');
        }, false, false);
        $pid = $process->start();
        $this->works[$index] = $pid;
        return $pid;
    }

    public function getTitle(string $html, array $fields = [], $bookname, $id) {
        $return = [];
        $document = new \DOMDocument();
        @$document->loadHTML($html);
        $xpath = new \DOMXPath($document);
        if (!empty($fields)) {
            $sql3 = '';
            foreach ($fields as $fields_k => $fields_v) {
                $elements_s[$fields_k] = $xpath->query($fields_v['select']);

                if ($elements_s[$fields_k]->length != 0) {
                    for ($i = 0; $i < $elements_s[$fields_k]->length; $i++) {
                        $title = $elements_s[$fields_k][$i]->nodeValue;
                        $title = addslashes($title);
                        $url = $elements_s[$fields_k][$i]->attributes[0]->nodeValue;

                        //$sql3 .= "($id .'".$bookname ."','".$title."','".$url."'),";
                        $sql3 .= '(' . $id . ',"' . $bookname . '","' . $title . '","' . $url . '"),';
                        //$sql3 .= "('".$bookname ."','".$title."','".$url."'),";
                    }
                    $sql3 = rtrim($sql3, ',');
                }
            }
            //不想直接爬取内容页，先记录内容页url

        }
        return $sql3;

    }

    public function checkMpid(&$worker) {
        if (!\swoole_process::kill($this->mpid, 0)) {
            // 这句提示,实际是看不到的.需要写到日志中
            $log = "endTime: " . date("H:i:s") . "--Master process exited, I [{$worker->pid}] also quit\n";
            echo $log;
            $worker->exit();

        }
    }

    public function rebootProcess($ret) {
        $pid = $ret['pid'];
        $index = array_search($pid, $this->works);
        if ($index !== false) {
            $index = intval($index);
            $new_pid = $this->CreateProcess($index);
            echo "rebootProcess: {$index}={$new_pid} Done\n";
            return;
        }
        throw new \Exception('rebootProcess Error: no pid');
    }

//清理僵尸进程

    public function processWait() {
        while (1) {
            if (count($this->works)) {
                $ret = \swoole_process::wait();
                if ($ret) {
                    $this->rebootProcess($ret);
                }
            } else {
                break;
            }
        }
    }
}
